package com.linkhub.oms.admin.modules.weighing.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.linkhub.oms.admin.common.enums.OssObjectModuleEnum;
import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.modules.order.domain.vo.LogisticFreightVO;
import com.linkhub.oms.admin.modules.order.service.OrderBizService;
import com.linkhub.oms.admin.modules.oss.domain.vo.PutObjectResultVO;
import com.linkhub.oms.admin.modules.oss.service.AliyunOSSBizService;
import com.linkhub.oms.admin.modules.user.accountflow.service.IUserAccountFlowBizService;
import com.linkhub.oms.admin.modules.weighing.domain.param.WeighingPackageInfoParam;
import com.linkhub.oms.admin.modules.weighing.domain.param.WeighingPackagePicParam;
import com.linkhub.oms.admin.modules.weighing.domain.vo.WeighingPackageInfoResponse;
import com.linkhub.oms.admin.modules.weighing.domain.vo.WeighingPackagePicResponse;
import com.linkhub.oms.admin.modules.weighing.service.WeighingPackageInfoService;
import com.linkhub.oms.common.constant.WmsInfoConstant;
import com.linkhub.oms.common.enums.mp.DocumentTypeEnum;
import com.linkhub.oms.common.enums.mp.ExpenseTypeEnum;
import com.linkhub.oms.common.enums.mp.OrderStatusEnum;
import com.linkhub.oms.common.enums.mp.TransactionTypeEnum;
import com.linkhub.oms.common.util.CacheKeyAssist;
import com.linkhub.oms.common.util.QtBeanUtil;
import com.linkhub.oms.common.util.WmsUtil;
import com.linkhub.oms.common.util.json.QtFastjsonUtil;
import com.linkhub.oms.component.redis.locker.DistributedLocker;
import com.linkhub.oms.dao.mpservice.ILocalProductService;
import com.linkhub.oms.dao.mpservice.IOrderProductService;
import com.linkhub.oms.dao.mpservice.IOrderService;
import com.linkhub.oms.dao.mpservice.IShopProductSkuMappingService;
import com.linkhub.oms.dao.mpservice.IShopService;
import com.linkhub.oms.dao.mpservice.IWeighingMachinePackageInfoService;
import com.linkhub.oms.data.sync.api.track.domain.request.TrackBaseRequest;
import com.linkhub.oms.data.sync.api.track.domain.response.TrackBaseResponse;
import com.linkhub.oms.data.sync.api.track.domain.response.TrackRegisterAcceptedData;
import com.linkhub.oms.data.sync.api.wms.domain.dto.WmsEntryOrderBatchCreateDTO;
import com.linkhub.oms.data.sync.api.wms.domain.response.EntryOrderBatchCreateResponse;
import com.linkhub.oms.data.sync.service.ShopifyDataSyncBizService;
import com.linkhub.oms.data.sync.service.TrackApiService;
import com.linkhub.oms.data.sync.service.WMSApiService;
import com.linkhub.oms.entity.LocalProductEntity;
import com.linkhub.oms.entity.OrderEntity;
import com.linkhub.oms.entity.OrderProductEntity;
import com.linkhub.oms.entity.ShopEntity;
import com.linkhub.oms.entity.ShopProductSkuMappingEntity;
import com.linkhub.oms.entity.UserAccountFlowEntity;
import com.linkhub.oms.entity.WeighingMachinePackageInfoEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;

import static com.linkhub.oms.common.constant.WeighingPackageConstant.WEIGHING_PACKAGE_KEY;

/**
 * @author Jaycle
 * @version 1.0.0
 * @Description WeighingPackageInfoServiceImpl.java
 * @createTime 2024/10/03 21:42
 */
@Slf4j
@Service
public class WeighingPackageInfoServiceImpl implements WeighingPackageInfoService {

    @Resource
    private IOrderService orderService;

    @Resource
    private IWeighingMachinePackageInfoService weighingMachinePackageInfoService;

    @Resource
    private DistributedLocker distributedLocker;

    @Resource
    private OrderBizService orderBizService;

    @Resource
    private IShopService shopService;

    @Resource
    private ShopifyDataSyncBizService shopifyDataSyncBizService;

    @Resource
    private AliyunOSSBizService aliyunOSSBizService;

    @Resource
    private IUserAccountFlowBizService userAccountFlowBizService;

    @Resource
    private ILocalProductService localProductService;

    @Resource
    private WMSApiService wmsApiService;

    @Resource
    private IOrderProductService orderProductService;

    @Resource
    private IShopProductSkuMappingService shopProductSkuMappingService;

    @Resource
    private TrackApiService trackApiService;

    @Override
    public WeighingPackageInfoResponse weighingPackageInfo( WeighingPackageInfoParam weighingPackageInfoParam ) {
        log.info("包裹称重信息参数：{}",weighingPackageInfoParam);
        String ticketsNum = weighingPackageInfoParam.getTicketsNum();
        OrderEntity orderEntity = orderService.getByWayBillNumber(ticketsNum);
        if (orderEntity == null) {
            return WeighingPackageInfoResponse.createNotExistResult();
        }
        if (!Objects.equals(orderEntity.getOrderStatus(), OrderStatusEnum.DELIVERED)) {
            return WeighingPackageInfoResponse.createNotDeliveredResult();
        }

        // ticketsNum加锁
        String lockKey = CacheKeyAssist.getShopifyDataSyncLockKey(ticketsNum, WEIGHING_PACKAGE_KEY);
        try {
            if (!distributedLocker.tryLock(lockKey)) {
                return WeighingPackageInfoResponse.createProcessingResult();
            }
            WeighingMachinePackageInfoEntity weighingMachinePackageInfoEntity = weighingMachinePackageInfoService.getByTicketsNum(ticketsNum);
            // 重复扫描包裹直接返回处理成功，必须限制重量大于0，因为图片接口也会插入包裹数据
            if (weighingMachinePackageInfoEntity != null && weighingMachinePackageInfoEntity.getWeight() != null) {
                return WeighingPackageInfoResponse.createOneSuccessResult();
            }

            List<OrderEntity> orderEntityList = new ArrayList<>(Collections.singletonList(orderEntity));

            // 对比可推送订单是否有带更新数据
            boolean updateFlag = orderBizService.syncOrderIfNecessary(orderEntityList);

            ShopEntity shopEntity = null;
            if (updateFlag) {
                // 同步订单
                try {
                    shopEntity = shopService.getByShopId(orderEntity.getSysShopId());
                    shopifyDataSyncBizService.syncShopOrders(shopEntity);
                } catch (Exception e) {
                    return WeighingPackageInfoResponse.createSyncFailureResult();
                }
            }
            // 获取订单最新数据
            orderEntity = orderService.getByOrderId(orderEntity.getSysOrderId());
            // 如果订单已取消状态，作退货处理
            if (OrderStatusEnum.CANCELLED.equals(orderEntity.getOrderStatus())) {

                WmsEntryOrderBatchCreateDTO wmsCreateWarehouseWarrantDTO = new WmsEntryOrderBatchCreateDTO();
                wmsCreateWarehouseWarrantDTO.setEntryOrderCode(orderEntity.getSysOrderId());
                wmsCreateWarehouseWarrantDTO.setOwnerCode(WmsInfoConstant.OWNER_CODE);
                wmsCreateWarehouseWarrantDTO.setWarehouseCode(WmsInfoConstant.WAREHOUSE_CODE);
                wmsCreateWarehouseWarrantDTO.setOrderType("WLTH");
                wmsCreateWarehouseWarrantDTO.setExpectStartTime(DateUtil.format(new Date(), DatePattern.UTC_SIMPLE_PATTERN));
                wmsCreateWarehouseWarrantDTO.setLogisticsName("YunExpress");
                wmsCreateWarehouseWarrantDTO.setExpressCode(orderEntity.getWayBillNumber());
                wmsCreateWarehouseWarrantDTO.setSupplierCode("0");
                wmsCreateWarehouseWarrantDTO.setUserDefined1(shopEntity.getUserId());
                List<OrderProductEntity> orderProductEntities1 = orderProductService.listBySysOrderId(orderEntity.getSysOrderId());
                orderProductEntities1 = orderProductEntities1.stream()
                        .peek(ord -> {
                            if (StringUtils.isBlank(ord.getSkuId())) {
                                ShopProductSkuMappingEntity byShopSkuId = shopProductSkuMappingService.getByShopSkuId(ord.getShopSkuId());
                                ord.setSkuId(byShopSkuId.getSkuId());
                            }

                        }).collect(Collectors.toList());
                List<WmsEntryOrderBatchCreateDTO.ProductParam> products = Lists.newArrayList();
                for (OrderProductEntity orderProduct : orderProductEntities1) {
                    WmsEntryOrderBatchCreateDTO.ProductParam product = new WmsEntryOrderBatchCreateDTO.ProductParam();
                    products.add(product);
                    LocalProductEntity localProductEntity = localProductService.getBySkuId(orderProduct.getSkuId());
                    product.setItemCode(WmsUtil.createItemCode(localProductEntity.getUserId(), localProductEntity.getSkuId()));
                    product.setPlanQty(String.valueOf(orderProduct.getCurrentQuantity()));
                }
                wmsCreateWarehouseWarrantDTO.setProductInfo(products);
                wmsCreateWarehouseWarrantDTO.setOutBizCode(orderEntity.getSysOrderId());
                EntryOrderBatchCreateResponse entryOrderBatchCreateResponse = wmsApiService.batchCreateEntryOrder(wmsCreateWarehouseWarrantDTO);
                if (!entryOrderBatchCreateResponse.success()) {
                    log.error("退货入库单创建失败，入库单信息：{}， 响应：{}",
                            QtFastjsonUtil.toJSONString(wmsCreateWarehouseWarrantDTO), QtFastjsonUtil.toJSONString(entryOrderBatchCreateResponse));
                    throw ExceptionFactory.getI18nBizException("wms.create.entry.order.back.fail");
                }
                List<UserAccountFlowEntity> unFreezeFlows = userAccountFlowBizService.queryAccountFlow(orderEntity.getSysOrderId(), TransactionTypeEnum.UN_FREEZE, DocumentTypeEnum.ORDER);

                if (CollUtil.isEmpty(unFreezeFlows)) {
                    // 解冻
                    log.info("订单费用开始解冻，订单号：{}",orderEntity.getSysOrderId());
                    userAccountFlowBizService.unfreezeAccountFlowByDocumentId(orderEntity.getSysOrderId(), DocumentTypeEnum.ORDER);
                } else {
                    // 退款
                    log.info("订单费用开始退款，订单号：{}",orderEntity.getSysOrderId());
                    userAccountFlowBizService.refundOrderAccountFlowByDocumentId(orderEntity.getSysOrderId());

                }
                // 保存包裹数据到数据库
                saveWeighingPackageInfo(weighingMachinePackageInfoEntity, weighingPackageInfoParam);
                return WeighingPackageInfoResponse.createTwoSuccessResult();
            }

            // 重新计算运费，解冻并扣除实际运费
            // 计算运费
            LogisticFreightVO logisticFreightVO = orderBizService.queryLogisticFreightByPackage(orderEntity.getSysOrderId(),weighingPackageInfoParam.getWeight(),weighingPackageInfoParam.getVolume());

            BigDecimal estimatedFreight = Convert.toBigDecimal(logisticFreightVO.getEstimatedFreight(),BigDecimal.ZERO);
            BigDecimal registrationFreight = Convert.toBigDecimal(logisticFreightVO.getRegistrationFreight(),BigDecimal.ZERO);
            // 解冻，并支付,其中运费和挂号费支付最新计算的费用
            Map<ExpenseTypeEnum, BigDecimal> realPayMap = Maps.newHashMap();
            realPayMap.put(ExpenseTypeEnum.FREIGHT,estimatedFreight);
            realPayMap.put(ExpenseTypeEnum.REGISTRATION_FEE, registrationFreight);
            userAccountFlowBizService.unfreezeAccountFlowAndPayByDocumentId(orderEntity.getSysOrderId(), DocumentTypeEnum.ORDER,realPayMap);


            TrackBaseRequest trackRequest = new TrackBaseRequest();
            trackRequest.setNumber(ticketsNum);
            TrackBaseResponse<TrackRegisterAcceptedData> trackResponse=trackApiService.registerTrack(Lists.newArrayList(trackRequest));
            if(!trackResponse.success()){
                log.info("订单物流追踪单号注册失败！订单号：{},运单号：{},{}",orderEntity.getSysOrderId(),ticketsNum,trackResponse.getData().getErrors());
            }
            // 保存包裹数据到数据库
            saveWeighingPackageInfo(weighingMachinePackageInfoEntity, weighingPackageInfoParam);
            // 更新订单发货日期
            OrderEntity update = new OrderEntity();
            update.setDeliveryTime(LocalDateTime.now());
            orderService.updateOrderInfo(orderEntity.getSysOrderId(),update);
            return WeighingPackageInfoResponse.createOneSuccessResult();
        }finally {
            distributedLocker.unlock(lockKey);
        }
    }

    private void saveWeighingPackageInfo( WeighingMachinePackageInfoEntity weighingMachinePackageInfoEntity, WeighingPackageInfoParam weighingPackageInfoParam ) {
        if (weighingMachinePackageInfoEntity == null) {
            WeighingMachinePackageInfoEntity entity = new WeighingMachinePackageInfoEntity();
            QtBeanUtil.copyProperties(weighingPackageInfoParam, entity);
            weighingMachinePackageInfoService.save(entity);
        } else {
            QtBeanUtil.copyProperties(weighingPackageInfoParam, weighingMachinePackageInfoEntity);
            weighingMachinePackageInfoService.updateById(weighingMachinePackageInfoEntity);
        }
    }

    @Override
    public WeighingPackagePicResponse weighingPackagePic( WeighingPackagePicParam weighingPackagePicParam ) {
        try {
            String picture = weighingPackagePicParam.getPicture();
            String ticketsNum = weighingPackagePicParam.getTicketsNum();
            PutObjectResultVO resultVO = aliyunOSSBizService.upload(OssObjectModuleEnum.WEIGHING_MACHINE_IMAGE, base64ToInputStream(picture), getWeighingPackagePicName(ticketsNum));
            saveWeighingPackagePic(ticketsNum, resultVO.getUrl());
            return WeighingPackagePicResponse.createSuccessResult();
        } catch (Exception e) {
            log.info("图片上传阿里云失败", e);
            return WeighingPackagePicResponse.createFailedResult();
        }
    }

    private InputStream base64ToInputStream( String base64String ) {
        // 解码 Base64 字符串
        byte[] bytes = Base64.getDecoder().decode(base64String);
        // 返回一个新的 ByteArrayInputStream
        return new ByteArrayInputStream(bytes);
    }

    private String getWeighingPackagePicName( String ticketsNum ) {
        return ticketsNum + ".jpg";
    }

    private void saveWeighingPackagePic( String ticketsNum, String url ) {
        WeighingMachinePackageInfoEntity weighingMachinePackageInfoEntity = weighingMachinePackageInfoService.getByTicketsNum(ticketsNum);
        if (weighingMachinePackageInfoEntity == null) {
            WeighingMachinePackageInfoEntity entity = new WeighingMachinePackageInfoEntity();
            entity.setTicketsNum(ticketsNum);
            entity.setUrl(url);
            weighingMachinePackageInfoService.save(entity);
        } else {
            weighingMachinePackageInfoEntity.setUrl(url);
            weighingMachinePackageInfoService.updateById(weighingMachinePackageInfoEntity);
        }
    }

}
